#include "Worker.h"
#include "Zipper/Zipper.h"
#include "SingletonHolder.h"
#include <boost/filesystem.hpp>
#include <boost/thread/mutex.hpp>



Worker::Worker(PComunicator::DataContainer theContainer,Validator::Scheme theScheme,std::string theAdress,std::string thePort,std::string theDirectory) : myClient(new Client(theAdress,thePort))
{
	myContainer= theContainer;
	myScheme = theScheme;
	myDirectory = theDirectory;
	myAllOK = false;

	myClient->Connect();
}


bool Worker::IsOK()
{
	return myAllOK;
}


void Worker::operator()()
{
	std::vector<PComunicator::PFileInfo> aReceivedFiles = myContainer.GetContainer<PComunicator::PFileInfo>();

	if(aReceivedFiles.size() < 1)
	{
		myAllOK = false;
		return;
	}
	
	std::vector<std::string> aStringData = myContainer.GetContainer<std::string>();
	std::string zip_location = write_data(aReceivedFiles[0],aStringData[0]);

	Zipper aZipper(aReceivedFiles[0]); //predpokladame ze na vstup, teda z web rozhrania stale pride len jeden subor !
	Validator::Scheme aZipScheme = aZipper.GetScheme();

	if(myScheme == aZipScheme)
	{
		std::vector<Validator::MetaFile> aFiles = myScheme.GetFilesToExtract();
		std::vector<boost::shared_ptr<PComunicator::PFileInfo> > aExtractedFiles;

		for(std::size_t i=0; i < aFiles.size(); i++)
		{
			if(aFiles[i].DoExtract())
			{
                PComunicator::PFileInfo *aExtracted = NULL;
				if(aZipper.ExtractNoType(aFiles[i].GetName(),&aExtracted))
				{
					aExtractedFiles.push_back(boost::shared_ptr<PComunicator::PFileInfo>(aExtracted));
				}
			}
		}
		
		send_data(aExtractedFiles,zip_location,"DBS");		// !TODO! Hardkodovane zmenit aby sa vyberalo z schemy
	}
	else
	{
		myAllOK = false;
		SingletonHolder::Instance().WriteMsg("The scheme for the received data doesnt match the predefined scheme!");
	}
}



void Worker::send_data(std::vector<boost::shared_ptr<PComunicator::PFileInfo> > &theInput,
																				std::string theZipPath,
																				std::string predmet)
{
	if(myClient->IsConnected())
	{
		std::vector<std::string> aStringData = myContainer.GetContainer<std::string>();
		PComunicator::DataContainer new_container;

		new_container.AddCommand("convert",false);

		//pridame data ktore sme prijali (z web stranky)
		for(std::size_t i = 0; i < aStringData.size(); i++)
		{
			new_container.AddData(aStringData[i]);
		}
		
		new_container.AddData(predmet);			//pridame info o predmete pre ktory sa robi kontrola
		new_container.AddData(theZipPath);		//pridame cestu k zipu

		//pridame rozbalene subory
		for (std::size_t i =0; i < theInput.size(); i++)
		{
			new_container.AddData((*theInput[i]));
		}

		myClient->Write(new_container);
		myAllOK = true;
	}

	myAllOK = false;
}


std::string Worker::write_data(PComunicator::PFileInfo theFile,std::string theUserLogin)
{
	boost::mutex aMutex;
	boost::mutex::scoped_lock aLock(aMutex);

	try
	{
		//vytvorime adresar kam sa ulozi subor
		std::string new_dir = myDirectory + theUserLogin +"/";
		boost::filesystem::create_directories(new_dir);

		//ulozime subor do vytvoreneho adresara
		theFile.Save(new_dir);

		return new_dir+theFile.GetFullName();
	}
	catch(const boost::filesystem::filesystem_error &ex)
	{
		SingletonHolder::Instance().WriteEx(ex.what());
		return theFile.GetFullName();
	}

}